﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.Attributes;
using Autodesk.Revit.DB;
using Autodesk.Revit.Exceptions;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.LIB;
using YArchitech.Revit;
using YArchitech.Revit.RevitExtension;

namespace YArchitech.HVAC
{
	[Transaction(TransactionMode.Manual)]
	[Regeneration(RegenerationOption.Manual)]
	internal class CmdQuickLocate : IExternalCommand
	{
		public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
		{
			Document document = commandData.Application.ActiveUIDocument.Document;
			UIApplication application = commandData.Application;
			UIDocument activeUIDocument = commandData.Application.ActiveUIDocument;
			Selection selection = application.ActiveUIDocument.Selection;
			List<ViewType> matchedViewType = this.GetMatchedViewType();
			if (!YJKRevitTools.ViewCheck(activeUIDocument, matchedViewType))
			{
				return Autodesk.Revit.UI.Result.Cancelled;
			}
			SketchPlane sketchPlane = document.ActiveView.SketchPlane;
			if (sketchPlane == null)
			{
				sketchPlane = this.CreateWorkPlane(document);
			}
			Plane plane = sketchPlane.GetPlane();
			int locateType = 0;
			switch (new UserSetting().GetQuickPositionType())
			{
			case QuickPosition.QuickType.Proximity:
				locateType = 0;
				break;
			case QuickPosition.QuickType.Wall:
				locateType = 2;
				break;
			case QuickPosition.QuickType.Grid:
				locateType = 1;
				break;
			}
			for (;;)
			{
				try
				{
					XYZ xyz = selection.PickPoint("该功能标注两点连线所穿过的所有平行的管道/风管/桥架/墙面/轴网的间距,请选择第一个点......");
					XYZ secondPnt = new XYZ();
					using (QuickLocateJip quickLocateJip = new QuickLocateJip(activeUIDocument))
					{
						quickLocateJip.StartPoint = xyz;
						secondPnt = quickLocateJip.PickEndPoint(xyz, "请选择第二个点...");
						quickLocateJip.Dispose();
					}
					if (secondPnt != null)
					{
						IList<FilterType> list = QuickMarkManager.GetElementByTwoPoint(document, xyz, secondPnt, plane);
						list = QuickMarkManager.GetMaxGroup(QuickMarkManager.FilterParallelPipes(list));
						QuickMarkManager.RemoveIntersected(list, secondPnt, document, locateType);
						if (list.Count < 2 || !QuickMarkManager.CheckDimension(list))
						{
							YJKMessageBox.Show("请选择平行的管道、风管、桥架、轴网或墙！");
							return Autodesk.Revit.UI.Result.Succeeded;
						}
						list = (from x in list
						orderby QuickMarkManager.GetDistance(x, secondPnt)
						select x).ToList<FilterType>();
						IList<IList<BaseMark>> markInfo = QuickMarkManager.GetMarkInfo(list, secondPnt, locateType);
						Transaction transaction = new Transaction(document, "生成标注");
						transaction.Start();
						try
						{
							Line line = null;
							DimensionType dimensionType = null;
							ReferenceArray referenceArray = null;
							Dictionary<Element, IList<int>> dictionary = new Dictionary<Element, IList<int>>();
							dimensionType = this.GetDimTypeByName(document, "HY-尺寸标注", "对角线 1.0mm");
							foreach (IEnumerable<BaseMark> enumerable in markInfo)
							{
								referenceArray = new ReferenceArray();
								foreach (BaseMark baseMark in enumerable)
								{
									XYZ lineVector = baseMark.Line.LineVector;
									XYZ ppoint = baseMark.PPoint;
                                    //(baseMark.Line.StartPoint + baseMark.Line.EndPoint) * 0.5;
									if (line == null)
									{
										line = Line.CreateBound(secondPnt, markInfo.Last<IList<BaseMark>>().Last<BaseMark>().PPoint);
									}
									Line curve = Line.CreateBound(ppoint.Subtract(lineVector * 0.0032808398950131233), ppoint);
									DetailCurve detailCurve = document.CreatYJKDetailCurve(document.ActiveView, curve);
									referenceArray.Append(detailCurve.GeometryCurve.Reference);
									if (!baseMark.IsLinkedElement)
									{
										if (dictionary.ContainsKey(baseMark.element))
										{
											dictionary[baseMark.element].Add(detailCurve.Id.IntegerValue);
										}
										else
										{
											IList<int> list2 = new List<int>();
											list2.Add(detailCurve.Id.IntegerValue);
											dictionary.Add(baseMark.element, list2);
										}
									}
								}
								if (!referenceArray.IsEmpty)
								{
									Dimension dimension = document.Create.NewDimension(document.ActiveView, line, referenceArray, dimensionType);
									dimensionType = dimension.DimensionType;
									if (dimensionType.GetParameter(BuiltInParameter.DIM_WITNS_LINE_CNTRL).AsInteger() == 0)
									{
										dimensionType.GetParameter(BuiltInParameter.DIM_WITNS_LINE_CNTRL).Set(1);
									}
									RevitDimensionExtension.ResetDimTextPos(dimension);
								}
							}
							if (dictionary.Count > 0)
							{
								this.BindExtData(dictionary);
							}
							document.Regenerate();
							transaction.Commit();
						}
						catch (Exception ex)
						{
							transaction.RollBack();
							YJKMessageBox.Show(ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
						}
						continue;
					}
				}
				catch (Autodesk.Revit.Exceptions.OperationCanceledException)
				{
					return Autodesk.Revit.UI.Result.Succeeded;
				}
				catch (Exception ex2)
				{
					string message2 = ex2.Message;
					YJKMessageBox.Show("请重新选择", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
				}
				break;
			}
			return Autodesk.Revit.UI.Result.Succeeded;
		}

		private SketchPlane CreateWorkPlane(Autodesk.Revit.DB.Document document)
		{
			Transaction transaction = new Transaction(document, "WorkPlane");
			transaction.Start();
			Plane plane = UnifiedModified.CreatePlane(document.ActiveView.ViewDirection, document.ActiveView.Origin);
			SketchPlane sketchPlane = document.CreatYJKSketchPlane(plane);
			document.ActiveView.SketchPlane = sketchPlane;
			transaction.Commit();
			return sketchPlane;
		}

		private List<ViewType> GetMatchedViewType()
		{
			return new List<ViewType>
			{
				(ViewType)1,
				(ViewType)2,
				(ViewType)3,
				(ViewType)117
			};
		}

		private void BindExtData(Dictionary<Element, IList<int>> storeDataDic)
		{
			if (storeDataDic == null || storeDataDic.Count <= 0)
			{
				return;
			}
			string arg = string.Empty;
			string key = string.Empty;
			string value = string.Empty;
			foreach (Element element in storeDataDic.Keys)
			{
				IDictionary<string, string> dictionary = new Dictionary<string, string>();
				Curve curve;
				if (element is Grid)
				{
					curve = (element as Grid).Curve;
				}
				else
				{
					curve = (element.Location as LocationCurve).Curve;
				}
				XYZ xyz = (curve.GetEndPoint(0) + curve.GetEndPoint(1)) * 0.5;
				IList<int> values = storeDataDic[element];
				value = string.Join<int>(",", values);
				arg = QuickMarkManager.PointToString(xyz);
				key = string.Format("{0};{1}", element.Id.IntegerValue.ToString(), arg);
				dictionary.Add(key, value);
				QuickMarkManager.StoreData(element, dictionary, true);
			}
		}

		private DimensionType GetDimTypeByName(Autodesk.Revit.DB.Document document, string strLabel, string strMark)
		{
			DimensionType dimensionType = null;
			foreach (Element element in new FilteredElementCollector(document).OfClass(typeof(DimensionType)).ToElements())
			{
				if (element.Name == strLabel)
				{
					dimensionType = (element as DimensionType);
					break;
				}
			}
			if (dimensionType == null)
			{
				dimensionType = (this.CopyTypeFromTemplate(document, typeof(DimensionType), strLabel, strMark) as DimensionType);
			}
			return dimensionType;
		}

		public Element CopyTypeFromTemplate(Autodesk.Revit.DB.Document doc, Type targetType, string strLabel, string strMark)
		{
			Element result = null;
			string versionNumber = RevitVersion.GetVersionNumber(doc);
			string text = Path.Combine(Product.FamilyLocation, versionNumber, "Template", "HYBIMSpace给排水样板.rte");
			Document document = null;
			if (!File.Exists(text))
			{
				return null;
			}
			document = doc.Application.OpenDocumentFile(text);
			Element element = null;
			foreach (Element element2 in new FilteredElementCollector(document).OfClass(targetType).ToElements())
			{
				if (element2.Name == strLabel)
				{
					element = element2;
					break;
				}
			}
			Element element3 = null;
			if (strMark.Trim() != "")
			{
				foreach (Element element4 in new FilteredElementCollector(document).OfClass(typeof(Autodesk.Revit.DB.ElementType)).ToElements())
				{
					if (element4.Name == strMark)
					{
						element3 = element4;
						break;
					}
				}
			}
			if (element == null && element3 == null)
			{
				return null;
			}
			if (element3 != null)
			{
				List<ElementId> list = new List<ElementId>();
				list.Add(element.Id);
				List<ElementId> list2 = new List<ElementId>();
				list2.Add(element3.Id);
				SubTransaction subTransaction = new SubTransaction(doc);
				subTransaction.Start();
				try
				{
					ICollection<ElementId> collection = ElementTransformUtils.CopyElements(document, list, doc, Transform.Identity, new CopyPasteOptions());
					ElementTransformUtils.CopyElements(document, list2, doc, Transform.Identity, new CopyPasteOptions());
					subTransaction.Commit();
					if (collection.Count > 0)
					{
						result = doc.GetElement(collection.ElementAt(0));
					}
					goto IL_209;
				}
				catch
				{
					subTransaction.RollBack();
					goto IL_209;
				}
			}
			List<ElementId> list3 = new List<ElementId>();
			list3.Add(element.Id);
			SubTransaction subTransaction2 = new SubTransaction(doc);
			subTransaction2.Start();
			try
			{
				ICollection<ElementId> collection2 = ElementTransformUtils.CopyElements(document, list3, doc, Transform.Identity, new CopyPasteOptions());
				subTransaction2.Commit();
				if (collection2.Count > 0)
				{
					result = doc.GetElement(collection2.ElementAt(0));
				}
			}
			catch
			{
				subTransaction2.RollBack();
			}
			IL_209:
			document.Close();
			return result;
		}
	}
}
